package thread;

class MyBlockingDeque {
    private int[] elem = null;
    private volatile int head = 0;
    private volatile int end = 0;
    private volatile int size = 0;

    public MyBlockingDeque(int capacity) {
        elem = new int[capacity];
    }

    // 放元素
    void myPut(int tmp) throws InterruptedException {
        synchronized (this) {
            while (size >= elem.length) {
                wait();
            }
            elem[end] = tmp;
            end++;
            if (end >= elem.length) {
                end = 0;
            }
            size++;
            notify();
        }
    }

    // 取元素
    int myTake() throws InterruptedException {
        synchronized (this) {
            while (size == 0) {
                wait();
            }
            int result = elem[head];
            head++;
            if (head >= elem.length) {
                head = 0;
            }
            size--;
            notify();
            return result;
        }
    }
}

public class test19 {
    public static void main(String[] args) throws InterruptedException {
        MyBlockingDeque queue = new MyBlockingDeque(1000);
        // 生产者模式
        Thread t1 = new Thread(() -> {
            int count = 1;
            while (true) {
                try {
                    queue.myPut(count);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(count);
                count++;
            }
        });
        // 消费者模式
        Thread t2 = new Thread(() -> {
            int count;
            while (true) {
                try {
                    count = queue.myTake();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(count);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.start();
        t2.start();
    }
}
